home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / games / IndiZone / vroom / merge.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  23.2 KB  |  1,033 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. #include <stdio.h>
  18. #include <math.h>
  19. #include <malloc.h>
  20.  
  21. #include "vroom.h"
  22. #include "track.h"
  23. #include "car.h"
  24. #include "body.h"
  25.  
  26. #define    FOLLOW_OK        0
  27. #define    FOLLOW_NEXT        1
  28. #define    FOLLOW_WIPE_OUT_LEFT    2
  29. #define    FOLLOW_WIPE_OUT_RIGHT    3
  30.  
  31. #define    BEGINNING    0x00
  32. #define    ENDING        0x01
  33. #define    LEFT_SIDE    0x00
  34. #define    RIGHT_SIDE    0x02
  35.  
  36. #define    CX_PART        0x04
  37. #define    CY_PART        0x08
  38. #define    DT_PART        0x0c
  39. #define    R_PART        0x10
  40.  
  41. #define    DXDS(t)            ( (t)->c[0] )
  42. #define    DYDS(t)            ( (t)->c[1] )
  43. #define    DXDL(t)            ( (t)->c[2] )
  44. #define    DYDL(t)            ( (t)->c[3] )
  45. #define    CX_LEFT_BEG(t)        ( (t)->c[4] )
  46. #define    CX_LEFT_END(t)        ( (t)->c[5] )
  47. #define    CX_RIGHT_BEG(t)        ( (t)->c[6] )
  48. #define    CX_RIGHT_END(t)        ( (t)->c[7] )
  49. #define    CY_LEFT_BEG(t)        ( (t)->c[8] )
  50. #define    CY_LEFT_END(t)        ( (t)->c[9] )
  51. #define    CY_RIGHT_BEG(t)        ( (t)->c[10] )
  52. #define    CY_RIGHT_END(t)        ( (t)->c[11] )
  53. #define    DTHETA_DS_LEFT_BEG(t)    ( (t)->c[12] )
  54. #define    DTHETA_DS_LEFT_END(t)    ( (t)->c[13] )
  55. #define    DTHETA_DS_RIGHT_BEG(t)    ( (t)->c[14] )
  56. #define    DTHETA_DS_RIGHT_END(t)    ( (t)->c[15] )
  57. #define    R_LEFT_BEG(t)        ( (t)->c[16] )
  58. #define    R_LEFT_END(t)        ( (t)->c[17] )
  59. #define    R_RIGHT_BEG(t)        ( (t)->c[18] )
  60. #define    R_RIGHT_END(t)        ( (t)->c[19] )
  61.  
  62. /* BEGIN PROTOTYPES -S merge.c */
  63. static void     addedMergeInTrack( Track *track ) ;
  64. static void     addedMergeOutTrack( Track *track ) ;
  65. static void     addToMergeTrack( Track *old, Track *new ) ;
  66. static void     drawMergeOutline( Track *track, int side ) ;
  67. static void     drawMergeTrack( Track *track, int lod ) ;
  68. static void     drawMergeTrackMarkers( Track *track, int lod ) ;
  69. static void     enterMergeOutTrack( Track *track, Car *car ) ;
  70. static int      followMergeTrack( Track *track, Car *car, float dTime ) ;
  71. static void     followTheMergeTrack( Track *track, Car *car, float dTime ) ;
  72. static void     freeMergeTrack( Track *track ) ;
  73. static void     getLocation( Track *track, float s, float lane, float *x,
  74.                     float *y, float *theta, float *radius ) ;
  75. static float    getTrackLength( Track *track, float lane ) ;
  76. static float    mergeLaneWidth( Track *track, float s, float lane1,
  77.                     float lane2 ) ;
  78. static float    topSpeedMergeTrack( Track *track, float s, float l ) ;
  79. /* END PROTOTYPES -S merge.c */
  80.  
  81.  
  82.  
  83. /*------------------------------------------------------------------------------
  84.  * Follow a merge piece of track.
  85.  *----------------------------------------------------------------------------*/
  86. static int
  87. followMergeTrack(
  88.     Track    *track,
  89.     Car    *car,
  90.     float    dTime
  91.     )
  92. {
  93.     int    doNext = 0 ;
  94.     int    laneLo ;
  95.     int    laneHi ;
  96.     float    length ;
  97.     float    radius ;
  98.     float    theta ;
  99.     float    c ;
  100.     float    s ;
  101.     float    eTime ;
  102.     float    newS ;
  103.     float    partialLane ;
  104.     Track    *nextTrack ;
  105.  
  106.     if( car->lane < 1.0f || car->lane > (float)track->lanes )
  107.     {
  108.         if( car->lane < 1.0f )
  109.         {
  110.             return( FOLLOW_WIPE_OUT_LEFT ) ;
  111.         }
  112.         else
  113.         {
  114.             return( FOLLOW_WIPE_OUT_RIGHT ) ;
  115.         }
  116.     }
  117.     else
  118.     {
  119.         laneLo = (int)floorf( car->lane ) ;
  120.         laneHi = (int)ceilf( car->lane ) ;
  121.         partialLane = car->lane - laneLo ;
  122.         length = partialLane * track->length[laneLo-1] +
  123.             ( 1.0f - partialLane ) * track->length[laneHi-1] ;
  124.         newS = car->s + car->speed * dTime / length ;
  125.         if( newS >= 1.0f )
  126.         {
  127.             eTime = ( 1.0f - car->s ) * length /
  128.                 car->speed ;
  129.             dTime -= eTime ;
  130.             car->s = 0.0f ;
  131.             car->track = track->nextTrack ;
  132.             incrementLap( car, dTime ) ;
  133.             if( track->type == MERGE_IN_TRACK )
  134.             {
  135.                 if( car->lane < 2.0f )
  136.                 {
  137.                     car->lane = 1.0f ;
  138.                 }
  139.                 else if( car->lane > track->lanes - 1 )
  140.                 {
  141.                     car->lane = track->lanes - 2 ;
  142.                 }
  143.                 else
  144.                 {
  145.                     car->lane -= 1.0f ;
  146.                 }
  147.                 laneLo = (int)floorf( car->lane ) ;
  148.                 laneHi = (int)ceilf( car->lane ) ;
  149.                 partialLane = car->lane - laneLo ;
  150.             }
  151.             car->track->enter( car->track, car ) ;
  152.             doNext = 1 ;
  153.         }
  154.         else
  155.         {
  156.             eTime = dTime ;
  157.             car->s = newS ;
  158.         }
  159.         if( car->status & CHANGE_LANE_RIGHT )
  160.         {
  161.             partialLane += eTime * LANE_CHANGE_SPEED ;
  162.             if( partialLane > 1.0f )
  163.             {
  164.                 car->status &= ~CHANGE_LANE_RIGHT ;
  165.                 car->lane = laneLo + 1.0f ;
  166.             }
  167.             else
  168.             {
  169.                 car->lane = laneLo + partialLane ;
  170.             }
  171.         }
  172.         else if( car->status & CHANGE_LANE_LEFT )
  173.         {
  174.             partialLane = laneHi - car->lane ;
  175.             partialLane += eTime * LANE_CHANGE_SPEED ;
  176.             if( partialLane > 1.0f )
  177.             {
  178.                 car->status &= ~CHANGE_LANE_LEFT ;
  179.                 car->lane = laneHi - 1.0f ;
  180.             }
  181.             else
  182.             {
  183.                 car->lane = laneHi - partialLane ;
  184.             }
  185.         }
  186.         if( doNext )
  187.         {
  188.             car->track->follow( car->track, car, dTime ) ;
  189.             return( FOLLOW_NEXT ) ;
  190.         }
  191.     }
  192.  
  193.     return( FOLLOW_OK ) ;
  194. }
  195.  
  196.  
  197.  
  198. /*------------------------------------------------------------------------------
  199.  * Follow a merge piece of track.
  200.  *----------------------------------------------------------------------------*/
  201. static void
  202. followTheMergeTrack(
  203.     Track    *track,
  204.     Car    *car,
  205.     float    dTime
  206.     )
  207. {
  208.     float    wvx ;
  209.     float    wvy ;
  210.     float    radius ;
  211.     float    theta ;
  212.     float    c ;
  213.     float    s ;
  214.     float    force ;
  215.  
  216.     switch( followMergeTrack( track, car, dTime ) )
  217.     {
  218.         case FOLLOW_OK :
  219.             getLocation( track, car->s, car->lane, &car->x, &car->y,
  220.                     &theta, &radius ) ;
  221.             car->theta = theta ;
  222.             force = centrifugalForce( car->speed, radius ) ;
  223.             if( force >= 1.0f )
  224.             {
  225.                 wvx = cosf( theta + (float)M_PI * 0.3333f ) ;
  226.                 wvy = sinf( theta + (float)M_PI * 0.3333f ) ;
  227.                 wipeOutCar( car, wvx, wvy, 1, WIPE_OUT_SPEED ) ;
  228.             }
  229.             else if( force > 0.0f )
  230.             {
  231.                 startSkid( car, force, dTime ) ;
  232.             }
  233.             else
  234.             {
  235.                 if( car->status & CAR_SKID )
  236.                 {
  237.                     stopSkid( car ) ;
  238.                 }
  239.             }
  240.             break ;
  241.  
  242.         case FOLLOW_NEXT :
  243.             break ;
  244.  
  245.         case FOLLOW_WIPE_OUT_LEFT :
  246.             theta = car->theta ;
  247.             wvx = cosf( theta + (float)M_PI * 0.8333f ) ;
  248.             wvy = sinf( theta + (float)M_PI * 0.8333f ) ;
  249.             wipeOutCar( car, wvx, wvy, -1, WIPE_OUT_OFF_ROAD ) ;
  250.             break ;
  251.  
  252.         case FOLLOW_WIPE_OUT_RIGHT :
  253.             theta = car->theta ;
  254.             wvx = cosf( theta + (float)M_PI * 0.3333f ) ;
  255.             wvy = sinf( theta + (float)M_PI * 0.3333f ) ;
  256.             wipeOutCar( car, wvx, wvy, 1, WIPE_OUT_OFF_ROAD ) ;
  257.             break ;
  258.     }
  259. }
  260.  
  261.  
  262.  
  263. /*------------------------------------------------------------------------------
  264.  * Initialize after adding track.
  265.  *----------------------------------------------------------------------------*/
  266. static void
  267. addedMergeInTrack(
  268.     Track    *track
  269.     )
  270. {
  271.     int    i ;
  272.     float    radius ;
  273.     float    ct ;
  274.     float    st ;
  275.     float    len ;
  276.     float    r ;
  277.     float    a ;
  278.     float    dt ;
  279.  
  280.     len = track->length[0] ;
  281.  
  282.     ct = cosf( track->theta ) ;
  283.     st = sinf( track->theta ) ;
  284.     DXDS( track ) = -st * len ;
  285.     DYDS( track ) = ct * len ;
  286.     DXDL( track ) = ct * LANE_WIDTH ;
  287.     DYDL( track ) = st * LANE_WIDTH ;
  288.  
  289.     a = len * len + LANE_WIDTH * LANE_WIDTH ;
  290.     r = a / ( 4.0f * LANE_WIDTH ) ;
  291.     dt = 2.0f * asinf( 2.0f * LANE_WIDTH * len / a ) ;
  292.  
  293.     a = r - ( track->midLane - 1.0f ) * LANE_WIDTH ;
  294.  
  295.     CX_LEFT_BEG( track ) = track->x + a * ct ;
  296.     CY_LEFT_BEG( track ) = track->y + a * st ;
  297.     DTHETA_DS_LEFT_BEG( track ) = -dt ;
  298.     R_LEFT_BEG( track ) = -r ;
  299.  
  300.     CX_RIGHT_BEG( track ) = track->x - a * ct ;
  301.     CY_RIGHT_BEG( track ) = track->y - a * st ;
  302.     DTHETA_DS_RIGHT_BEG( track ) = dt ;
  303.     R_RIGHT_BEG( track ) = r ;
  304.  
  305.     a = r + ( track->midLane - 2.0f ) * LANE_WIDTH ;
  306.  
  307.     CX_LEFT_END( track ) = track->x - st * len - a * ct ;
  308.     CY_LEFT_END( track ) = track->y + ct * len - a * st ;
  309.     DTHETA_DS_LEFT_END( track ) = dt ;
  310.     R_LEFT_END( track ) = r ;
  311.  
  312.     CX_RIGHT_END( track ) = track->x - st * len + a * ct ;
  313.     CY_RIGHT_END( track ) = track->y + ct * len + a * st ;
  314.     DTHETA_DS_RIGHT_END( track ) = -dt ;
  315.     R_RIGHT_END( track ) = -r ;
  316.  
  317.     track->length[0] = 1.0f * r * dt ;
  318.     track->length[track->lanes-1] = 1.0f * r * dt ;
  319.  
  320.     for( i = 0 ; i < MAX_LOD ; i++ )
  321.     {
  322.         glNewList( track->drawList+i, GL_COMPILE ) ;
  323.         drawMergeTrack( track, i ) ;
  324.         glEndList() ;
  325.         glNewList( track->drawMarkerList+i, GL_COMPILE ) ;
  326.         drawMergeTrackMarkers( track, i ) ;
  327.         glEndList() ;
  328.     }
  329.  
  330.     /*
  331.      * Compute the cull radius from the center point.
  332.      */
  333.     radius = 0.5f * track->lanes * LANE_WIDTH + SIDE_MARKER_WIDTH ;
  334.     radius = 0.5f * sqrtf( track->length[1] * track->length[1] +
  335.         radius * radius ) ;
  336.  
  337.     track->center[0] = track->x + 0.5f * DXDS( track ) ;
  338.     track->center[1] = track->y + 0.5f * DYDS( track ) ;
  339.     track->center[2] = 0.0f ;
  340.  
  341.     track->cullDetail = trackDetail( radius ) ;
  342. }
  343.  
  344.  
  345.  
  346. /*------------------------------------------------------------------------------
  347.  * Initialize after adding track.
  348.  *----------------------------------------------------------------------------*/
  349. static void
  350. addedMergeOutTrack(
  351.     Track    *track
  352.     )
  353. {
  354.     int    i ;
  355.     float    radius ;
  356.     float    ct ;
  357.     float    st ;
  358.     float    len ;
  359.     float    r ;
  360.     float    a ;
  361.     float    dt ;
  362.  
  363.     len = track->length[0] ;
  364.  
  365.     ct = cosf( track->theta ) ;
  366.     st = sinf( track->theta ) ;
  367.     DXDS( track ) = -st * len ;
  368.     DYDS( track ) = ct * len ;
  369.     DXDL( track ) = ct * LANE_WIDTH ;
  370.     DYDL( track ) = st * LANE_WIDTH ;
  371.  
  372.     a = len * len + LANE_WIDTH * LANE_WIDTH ;
  373.     r = a / ( 4.0f * LANE_WIDTH ) ;
  374.     dt = 2.0f * asinf( 2.0f * LANE_WIDTH * len / a ) ;
  375.  
  376.     a = r + ( track->midLane - 2.0f ) * LANE_WIDTH ;
  377.  
  378.     CX_LEFT_BEG( track ) = track->x - a * ct ;
  379.     CY_LEFT_BEG( track ) = track->y - a * st ;
  380.     DTHETA_DS_LEFT_BEG( track ) = dt ;
  381.     R_LEFT_BEG( track ) = r ;
  382.  
  383.     CX_RIGHT_BEG( track ) = track->x + a * ct ;
  384.     CY_RIGHT_BEG( track ) = track->y + a * st ;
  385.     DTHETA_DS_RIGHT_BEG( track ) = -dt ;
  386.     R_RIGHT_BEG( track ) = -r ;
  387.  
  388.     a = r - ( track->midLane - 1.0f ) * LANE_WIDTH ;
  389.  
  390.     CX_LEFT_END( track ) = track->x - st * len + a * ct ;
  391.     CY_LEFT_END( track ) = track->y + ct * len + a * st ;
  392.     DTHETA_DS_LEFT_END( track ) = -dt ;
  393.     R_LEFT_END( track ) = -r ;
  394.  
  395.     CX_RIGHT_END( track ) = track->x - st * len - a * ct ;
  396.     CY_RIGHT_END( track ) = track->y + ct * len - a * st ;
  397.     DTHETA_DS_RIGHT_END( track ) = dt ;
  398.     R_RIGHT_END( track ) = r ;
  399.  
  400.     track->length[0] = r * dt ;
  401.     track->length[track->lanes-1] = r * dt ;
  402.  
  403.     for( i = 0 ; i < MAX_LOD ; i++ )
  404.     {
  405.         glNewList( track->drawList+i, GL_COMPILE ) ;
  406.         drawMergeTrack( track, i ) ;
  407.         glEndList() ;
  408.         glNewList( track->drawMarkerList+i, GL_COMPILE ) ;
  409.         drawMergeTrackMarkers( track, i ) ;
  410.         glEndList() ;
  411.     }
  412.  
  413.     /*
  414.      * Compute the cull radius from the center point.
  415.      */
  416.     radius = 0.5f * track->lanes * LANE_WIDTH + SIDE_MARKER_WIDTH ;
  417.     radius = 0.5f * sqrtf( track->length[0] * track->length[0] +
  418.         radius * radius ) ;
  419.  
  420.     track->center[0] = track->x + 0.5f * DXDS( track ) ;
  421.     track->center[1] = track->y + 0.5f * DYDS( track ) ;
  422.     track->center[2] = 0.0f ;
  423.  
  424.     track->cullDetail = trackDetail( radius ) ;
  425. }
  426.  
  427.  
  428.  
  429. /*------------------------------------------------------------------------------
  430.  * Create a N lane piece of merge in track.
  431.  *----------------------------------------------------------------------------*/
  432. Track *
  433. createMergeInTrack(
  434.     int    nLanes,
  435.     float    length
  436.     )
  437. {
  438.     int    i ;
  439.     float    r ;
  440.     Track    *track ;
  441.  
  442.     track = myMalloc( sizeof( Track ) ) ;
  443.  
  444.     track->lanes = nLanes ;
  445.     track->type = MERGE_IN_TRACK ;
  446.     track->x = 0.0f ;
  447.     track->y = 0.0f ;
  448.     track->theta = 0.0f ;
  449.     track->length = myMalloc( nLanes * sizeof( float ) ) ;
  450.     for( i = 0 ; i < nLanes ; i++ )
  451.     {
  452.         track->length[i] = length ;
  453.     }
  454.     track->midLane = 1.0f + 0.5f * ( nLanes - 1 ) ;
  455.     track->follow = followTheMergeTrack ;
  456.     track->add = addToMergeTrack ;
  457.     track->added = addedMergeInTrack ;
  458.     track->topSpeed = topSpeedMergeTrack ;
  459.     track->nextTrack = NULL ;
  460.     track->drawList = glGenLists( MAX_LOD ) ;
  461.     track->drawMarkerList = glGenLists( MAX_LOD ) ;
  462.     track->startPosition = NULL ;
  463.     track->endPosition = NULL ;
  464.     track->drawOutline = drawMergeOutline ;
  465.     track->trackLength = getTrackLength ;
  466.     track->enter = enterTrack ;
  467.     track->free = freeMergeTrack ;
  468.     track->cullDetail = NULL ;
  469.     track->laneWidth = mergeLaneWidth ;
  470.  
  471.     return( track ) ;
  472. }
  473.  
  474.  
  475.  
  476. /*------------------------------------------------------------------------------
  477.  * Create a N lane piece of merge out track.
  478.  *----------------------------------------------------------------------------*/
  479. Track *
  480. createMergeOutTrack(
  481.     int    nLanes,
  482.     float    length
  483.     )
  484. {
  485.     int    i ;
  486.     float    r ;
  487.     Track    *track ;
  488.  
  489.     track = myMalloc( sizeof( Track ) ) ;
  490.  
  491.     track->lanes = nLanes ;
  492.     track->type = MERGE_OUT_TRACK ;
  493.     track->x = 0.0f ;
  494.     track->y = 0.0f ;
  495.     track->theta = 0.0f ;
  496.     track->length = myMalloc( nLanes * sizeof( float ) ) ;
  497.     for( i = 0 ; i < nLanes ; i++ )
  498.     {
  499.         track->length[i] = length ;
  500.     }
  501.     track->midLane = 1.0f + 0.5f * ( nLanes - 1 ) ;
  502.     track->follow = followTheMergeTrack ;
  503.     track->add = addToMergeTrack ;
  504.     track->added = addedMergeOutTrack ;
  505.     track->topSpeed = topSpeedMergeTrack ;
  506.     track->nextTrack = NULL ;
  507.     track->drawList = glGenLists( MAX_LOD ) ;
  508.     track->drawMarkerList = glGenLists( MAX_LOD ) ;
  509.     track->startPosition = NULL ;
  510.     track->endPosition = NULL ;
  511.     track->drawOutline = drawMergeOutline ;
  512.     track->trackLength = getTrackLength ;
  513.     track->enter = enterMergeOutTrack ;
  514.     track->free = freeMergeTrack ;
  515.     track->cullDetail = NULL ;
  516.     track->laneWidth = mergeLaneWidth ;
  517.  
  518.     return( track ) ;
  519. }
  520.  
  521.  
  522.  
  523. /*------------------------------------------------------------------------------
  524.  * Add to a piece of curved track.
  525.  *----------------------------------------------------------------------------*/
  526. static void
  527. addToMergeTrack(
  528.     Track    *old,
  529.     Track    *new
  530.     )
  531. {
  532.     new->theta = old->theta ;
  533.     new->x = old->x + DXDS( old ) ;
  534.     new->y = old->y + DYDS( old ) ;
  535.     old->nextTrack = new ;
  536. }
  537.  
  538.  
  539.  
  540. /*------------------------------------------------------------------------------
  541.  * Draw the merge in track piece.
  542.  *----------------------------------------------------------------------------*/
  543. static void
  544. drawMergeTrack(
  545.     Track    *track,
  546.     int    lod
  547.     )
  548. {
  549.     int    i ;
  550.     int    n ;
  551.     int    l ;
  552.     GLfloat    w ;
  553.     GLfloat    t ;
  554.     GLfloat    c ;
  555.     GLfloat    s ;
  556.     GLfloat    ri ;
  557.     GLfloat    ro ;
  558.     GLfloat    v[4][2] ;
  559.  
  560.     /*
  561.      * Draw straight pieces first.
  562.      */
  563.     c = cosf( track->theta ) ;
  564.     s = sinf( track->theta ) ;
  565.  
  566.     v[0][1] = 0.0f ;
  567.     v[1][1] = 0.0f ;
  568.     v[2][1] = track->length[1] ;
  569.     v[3][1] = track->length[1] ;
  570.  
  571.     for( l = 1 ; l < track->lanes - 1 ; l++ )
  572.     {
  573.         w = ( (float)l - 0.5f * ( track->lanes - 1 ) ) * LANE_WIDTH ;
  574.         v[0][0] = w - 0.5f * RAIL_WIDTH ;
  575.         v[1][0] = w + 0.5f * RAIL_WIDTH ;
  576.         v[2][0] = w - 0.5f * RAIL_WIDTH ;
  577.         v[3][0] = w + 0.5f * RAIL_WIDTH ;
  578.         glBegin( GL_TRIANGLE_STRIP ) ;
  579.         for( i = 0 ; i < 4 ; i++ )
  580.         {
  581.             glVertex2f( track->x + v[i][0] * c - v[i][1] * s,
  582.                     track->y + v[i][0] * s + v[i][1] * c ) ;
  583.         }
  584.         glEnd() ;
  585.     }
  586.  
  587.     n = 16 - lod * 4 ;
  588.     if( n < 4 )
  589.     {
  590.         n = 4 ;
  591.     }
  592.  
  593.     /*
  594.      * Draw left side.
  595.      */
  596.     glBegin( GL_TRIANGLE_STRIP ) ;
  597.     for( i = 0 ; i < n ; i++ )
  598.     {
  599.         t = ( (float)i / (float)( n-1 ) ) ;
  600.         if( t < 0.5f )
  601.         {
  602.             ri = R_LEFT_BEG( track ) + 0.5f * RAIL_WIDTH ;
  603.             ro = ri - RAIL_WIDTH ;
  604.             t = track->theta + t * DTHETA_DS_LEFT_BEG( track ) ;
  605.             c = cosf( t ) ;
  606.             s = sinf( t ) ;
  607.             glVertex2f( CX_LEFT_BEG( track ) + ro * c,
  608.                     CY_LEFT_BEG( track ) + ro * s ) ;
  609.             glVertex2f( CX_LEFT_BEG( track ) + ri * c,
  610.                     CY_LEFT_BEG( track ) + ri * s ) ;
  611.         }
  612.         else
  613.         {
  614.             ri = R_LEFT_END( track ) + 0.5f * RAIL_WIDTH ;
  615.             ro = ri - RAIL_WIDTH ;
  616.             t = track->theta +
  617.                 ( t - 1.0f ) * DTHETA_DS_LEFT_END( track ) ;
  618.             c = cosf( t ) ;
  619.             s = sinf( t ) ;
  620.             glVertex2f( CX_LEFT_END( track ) + ro * c,
  621.                     CY_LEFT_END( track ) + ro * s ) ;
  622.             glVertex2f( CX_LEFT_END( track ) + ri * c,
  623.                     CY_LEFT_END( track ) + ri * s ) ;
  624.         }
  625.     }
  626.     glEnd() ;
  627.     /*
  628.      * Draw right side.
  629.      */
  630.     glBegin( GL_TRIANGLE_STRIP ) ;
  631.     for( i = 0 ; i < n ; i++ )
  632.     {
  633.         t = ( (float)i / (float)( n-1 ) ) ;
  634.         if( t < 0.5f )
  635.         {
  636.             ri = R_RIGHT_BEG( track ) + 0.5f * RAIL_WIDTH ;
  637.             ro = ri - RAIL_WIDTH ;
  638.             t = track->theta + t * DTHETA_DS_RIGHT_BEG( track ) ;
  639.             c = cosf( t ) ;
  640.             s = sinf( t ) ;
  641.             glVertex2f( CX_RIGHT_BEG( track ) + ro * c,
  642.                     CY_RIGHT_BEG( track ) + ro * s ) ;
  643.             glVertex2f( CX_RIGHT_BEG( track ) + ri * c,
  644.                     CY_RIGHT_BEG( track ) + ri * s ) ;
  645.         }
  646.         else
  647.         {
  648.             ri = R_RIGHT_END( track ) + 0.5f * RAIL_WIDTH ;
  649.             ro = ri - RAIL_WIDTH ;
  650.             t = track->theta +
  651.                 ( t - 1.0f ) * DTHETA_DS_RIGHT_END( track ) ;
  652.             c = cosf( t ) ;
  653.             s = sinf( t ) ;
  654.             glVertex2f( CX_RIGHT_END( track ) + ro * c,
  655.                     CY_RIGHT_END( track ) + ro * s ) ;
  656.             glVertex2f( CX_RIGHT_END( track ) + ri * c,
  657.                     CY_RIGHT_END( track ) + ri * s ) ;
  658.         }
  659.     }
  660.     glEnd() ;
  661. }
  662.  
  663.  
  664.  
  665. /*------------------------------------------------------------------------------
  666.  * Draw the left curved track markers.
  667.  *----------------------------------------------------------------------------*/
  668. static void
  669. drawMergeTrackMarkers(
  670.     Track    *track,
  671.     int    lod
  672.     )
  673. {
  674.     int    i ;
  675.     int    l ;
  676.     int    m ;
  677.     int    n ;
  678.     int    mask ;
  679.     GLfloat    w ;
  680.     GLfloat    t ;
  681.     GLfloat    c ;
  682.     GLfloat    s ;
  683.     GLfloat    ri ;
  684.     GLfloat    dri ;
  685.     GLfloat    ro ;
  686.     GLfloat    v[4][2] ;
  687.  
  688.     if( lod == MAX_LOD - 1 )
  689.     {
  690.         return ;
  691.     }
  692.  
  693.     n = (int)( ABSFUNC( R_LEFT_BEG( track ) * DTHETA_DS_LEFT_BEG( track ) )
  694.             / SIDE_MARKER_LENGTH );
  695.     n += ( 4 - ( n % 4 ) ) % 4 ;
  696.     m = LEFT_SIDE ;
  697.     dri = -0.5f * LANE_WIDTH ;
  698.     for( l = 0 ; l < 2 ; l++ )
  699.     {
  700.         glBegin( GL_QUADS ) ;
  701.         for( i = 0 ; i < n ; i++ )
  702.         {
  703.             if( ( i % 4 ) == 0 )
  704.             {
  705.                 glColor3f( 0.5f, 0.0f, 0.0f ) ;
  706.             }
  707.             else if( ( i % 2 ) == 0 )
  708.             {
  709.                 glColor3f( 0.9f, 0.9f, 0.9f ) ;
  710.             }
  711.             t = ( (float)i / (float)( n ) ) ;
  712.             if( t < 0.5f )
  713.             {
  714.                 mask = m | BEGINNING ;
  715.                 t = track->theta +
  716.                     t * track->c[DT_PART|mask] ;
  717.             }
  718.             else
  719.             {
  720.                 mask = m | ENDING ;
  721.                 t = track->theta +
  722.                     ( t - 1.0f ) * track->c[DT_PART|mask] ;
  723.             }
  724.             ri = track->c[R_PART|mask] + dri ;
  725.             ro = ri - SIDE_MARKER_WIDTH ;
  726.             c = cosf( t ) ;
  727.             s = sinf( t ) ;
  728.             if( i % 2 )
  729.             {
  730.                 glVertex2f( track->c[CX_PART|mask] + ri * c,
  731.                         track->c[CY_PART|mask] + ri * s ) ;
  732.                 glVertex2f( track->c[CX_PART|mask] + ro * c,
  733.                         track->c[CY_PART|mask] + ro * s ) ;
  734.             }
  735.             else
  736.             {
  737.                 glVertex2f( track->c[CX_PART|mask] + ro * c,
  738.                         track->c[CY_PART|mask] + ro * s ) ;
  739.                 glVertex2f( track->c[CX_PART|mask] + ri * c,
  740.                         track->c[CY_PART|mask] + ri * s ) ;
  741.             }
  742.         }
  743.         glEnd() ;
  744.         m = RIGHT_SIDE ;
  745.         dri = 0.5f * LANE_WIDTH + SIDE_MARKER_WIDTH ;
  746.     }
  747. }
  748.  
  749.  
  750.  
  751. /*------------------------------------------------------------------------------
  752.  * Draw the merge in track piece outline.
  753.  *----------------------------------------------------------------------------*/
  754. static void
  755. drawMergeOutline(
  756.     Track    *track,
  757.     int    side
  758.     )
  759. {
  760.     int    i ;
  761.     int    n = 5 ;
  762.     int    sideMask ;
  763.     int    mask ;
  764.     GLfloat    r ;
  765.     GLfloat    dr ;
  766.     GLfloat    t ;
  767.     GLfloat    c ;
  768.     GLfloat    cx ;
  769.     GLfloat    cy ;
  770.     GLfloat    s ;
  771.     GLfloat    a[2] ;
  772.  
  773.     if( side == TRACK_LEFT_SIDE )
  774.     {
  775.         dr = -0.5f * LANE_WIDTH ;
  776.     }
  777.     else
  778.     {
  779.         dr = 0.5f * LANE_WIDTH ;
  780.     }
  781.  
  782.     sideMask = ( side == TRACK_LEFT_SIDE ) ? LEFT_SIDE : RIGHT_SIDE ;
  783.     for( i = 0 ; i < n ; i++ )
  784.     {
  785.         t = ( (float)i / (float)( n - 1 ) ) ;
  786.         if( t <= 0.5f )
  787.         {
  788.             mask = sideMask | BEGINNING ;
  789.         }
  790.         else
  791.         {
  792.             mask = sideMask | ENDING ;
  793.             t = t - 1.0f ;
  794.         }
  795.         t = track->theta + t * track->c[DT_PART|mask] ;
  796.         r = track->c[R_PART|mask] + dr ;
  797.         c = cosf( t ) ;
  798.         s = sinf( t ) ;
  799.         a[0] = track->c[CX_PART|mask] + r * c ;
  800.         a[1] = track->c[CY_PART|mask] + r * s ;
  801.         glVertex2fv( a ) ;
  802.     }
  803. }
  804.  
  805.  
  806.  
  807. /*------------------------------------------------------------------------------
  808.  * Return the top speed of a left curved track.
  809.  *----------------------------------------------------------------------------*/
  810. static float
  811. topSpeedMergeTrack(
  812.     Track    *track,
  813.     float    s,
  814.     float    l
  815.     )
  816. {
  817.     float    radius ;
  818.  
  819.     if( l < 2.0f || l > (float)( track->lanes + 1 ) )
  820.     {
  821.         return( maxSpeed( ABSFUNC( R_LEFT_BEG( track ) ) ) ) ;
  822.     }
  823.     else
  824.     {
  825.         return( 1.5f * TOP_SPEED ) ;
  826.     }
  827. }
  828.  
  829.  
  830.  
  831. /*------------------------------------------------------------------------------
  832.  * Free up memory used by a piece of track.
  833.  *----------------------------------------------------------------------------*/
  834. static void
  835. freeMergeTrack(
  836.     Track    *track
  837.     )
  838. {
  839.     if( track )
  840.     {
  841.         free( track->length ) ;
  842.         free( track ) ;
  843.     }
  844. }
  845.  
  846.  
  847.  
  848. /*------------------------------------------------------------------------------
  849.  * Return the length of track at the given lane.
  850.  *----------------------------------------------------------------------------*/
  851. static float
  852. getTrackLength(
  853.     Track    *track,
  854.     float    lane
  855.     )
  856. {
  857.     float    f ;
  858.     int    n ;
  859.  
  860.     if( lane < 2.0f )
  861.     {
  862.         f = lane - 1.0f ;
  863.         return( track->length[0] + f *
  864.             ( track->length[1] - track->length[0] ) ) ;
  865.     }
  866.     else if( lane > (float)( track->lanes - 1 ) )
  867.     {
  868.         n = track->lanes - 1 ;
  869.         f = track->lanes - lane ;
  870.         return( track->length[n] + f *
  871.             ( track->length[n-1] - track->length[n] ) ) ;
  872.     }
  873.     else
  874.     {
  875.         return( track->length[1] ) ;
  876.     }
  877. }
  878.  
  879.  
  880.  
  881. /*------------------------------------------------------------------------------
  882.  * Return the x and y coordinate given the lane and s.
  883.  *----------------------------------------------------------------------------*/
  884. static void
  885. getLocation(
  886.     Track    *track,
  887.     float    s,
  888.     float    lane,
  889.     float    *x,
  890.     float    *y,
  891.     float    *theta,
  892.     float    *radius
  893.     )
  894. {
  895.     int    mask ;
  896.     float    st ;
  897.     float    xs ;
  898.     float    ys ;
  899.     float    cx ;
  900.     float    cy ;
  901.     float    r ;
  902.     float    t ;
  903.     float    dt ;
  904.  
  905.     /*
  906.      * Determine if in straight lane.
  907.      */
  908.     if( lane >= 2.0f && lane <= (float)( track->lanes - 1 ) )
  909.     {
  910.         *x = track->x + s * DXDS( track ) +
  911.             ( lane - track->midLane ) * DXDL( track ) ;
  912.         *y = track->y + s * DYDS( track ) +
  913.             ( lane - track->midLane ) * DYDL( track ) ;
  914.         *theta = track->theta ;
  915.         *radius = 1e20 ;
  916.         return ;
  917.     }
  918.     /*
  919.      * Located on first part of curved part of track.
  920.      */
  921.     else
  922.     {
  923.         if( s <= 0.5f )
  924.         {
  925.             mask = BEGINNING ;
  926.             st = s ;
  927.         }
  928.         else
  929.         {
  930.             mask = ENDING ;
  931.             st = s - 1.0f ;
  932.         }
  933.         if( lane < 2.0f )
  934.         {
  935.             mask |= LEFT_SIDE ;
  936.             dt = 2.0f - lane ;
  937.         }
  938.         else
  939.         {
  940.             mask |= RIGHT_SIDE ;
  941.             dt = lane - (float)track->lanes + 1.0f ;
  942.         }
  943.     }
  944.     r = track->c[R_PART | mask] ;
  945.     cx = track->c[CX_PART | mask] ;
  946.     cy = track->c[CY_PART | mask] ;
  947.     t = st * track->c[DT_PART | mask] ;
  948.  
  949.     *theta = dt * t + track->theta ;
  950.     t += track->theta ;
  951.     *x = cx + r * cosf( t ) ;
  952.     *y = cy + r * sinf( t ) ;
  953.     *radius = r ;
  954.  
  955.     if( dt < 1.0f )
  956.     {
  957.         dt = 1.0f - dt ;
  958.         if( lane < 2.0f )
  959.         {
  960.             lane = 2.0f ;
  961.         }
  962.         else
  963.         {
  964.             lane = (float)( track->lanes - 1 ) ;
  965.         }
  966.         *x += dt * ( track->x + s * DXDS( track ) +
  967.             ( lane - track->midLane ) * DXDL( track ) - *x ) ;
  968.         *y += dt * ( track->y + s * DYDS( track ) +
  969.             ( lane - track->midLane ) * DYDL( track ) - *y ) ;
  970.     }
  971. }
  972.  
  973.  
  974.  
  975. /*------------------------------------------------------------------------------
  976.  * Correct lanes when entering a merge-out track segment.
  977.  *----------------------------------------------------------------------------*/
  978. static void
  979. enterMergeOutTrack(
  980.     Track    *track,
  981.     Car    *car
  982.     )
  983. {
  984.     car->lane += 1.0f ;
  985. }
  986.  
  987.  
  988.  
  989. /*------------------------------------------------------------------------------
  990.  * Return the location of a point on the track.
  991.  *----------------------------------------------------------------------------*/
  992. static float
  993. mergeLaneWidth(
  994.     Track    *track,
  995.     float    s,
  996.     float    lane1,
  997.     float    lane2
  998.     )
  999. {
  1000.     float    x1 ;
  1001.     float    y1 ;
  1002.     float    t1 ;
  1003.     float    r1 ;
  1004.     float    x2 ;
  1005.     float    y2 ;
  1006.     float    t2 ;
  1007.     float    r2 ;
  1008.  
  1009.     if( lane1 < 1.0f )
  1010.     {
  1011.         lane1 = 1.0f ;
  1012.     }
  1013.     else if( lane1 > (float)track->lanes )
  1014.     {
  1015.         lane1 = (float)track->lanes ;
  1016.     }
  1017.     if( lane2 < 1.0f )
  1018.     {
  1019.         lane2 = 1.0f ;
  1020.     }
  1021.     else if( lane2 > (float)track->lanes )
  1022.     {
  1023.         lane2 = (float)track->lanes ;
  1024.     }
  1025.  
  1026.     getLocation( track, s, lane1, &x1, &y1, &t1, &r1 ) ;
  1027.     getLocation( track, s, lane2, &x2, &y2, &t2, &r2 ) ;
  1028.  
  1029.     x1 = x1 - x2 ;
  1030.     y1 = y1 - y2 ;
  1031.     return( sqrtf( x1*x1 + y1*y1 ) ) ;
  1032. }
  1033.